AArch64: Enable lower ELs to use pointer authentication
authorJeenu Viswambharan <[email protected]>
Wed, 15 Aug 2018 13:29:29 +0000 (14:29 +0100)
committerJeenu Viswambharan <[email protected]>
Tue, 16 Oct 2018 07:31:13 +0000 (08:31 +0100)
Pointer authentication is an Armv8.3 feature that introduces
instructions that can be used to authenticate and verify pointers.

Pointer authentication instructions are allowed to be accessed from all
ELs but only when EL3 explicitly allows for it; otherwise, their usage
will trap to EL3. Since EL3 doesn't have trap handling in place, this
patch unconditionally disables all related traps to EL3 to avoid
potential misconfiguration leading to an unhandled EL3 exception.

Fixes ARM-software/tf-issues#629

Change-Id: I9bd2efe0dc714196f503713b721ffbf05672c14d
Signed-off-by: Jeenu Viswambharan <[email protected]>
docs/firmware-design.rst
include/common/aarch64/el3_common_macros.S
include/lib/aarch64/arch.h
lib/el3_runtime/aarch64/context_mgmt.c

index 7cc74855ded3e3db0054a806aa9cb2cc1e06f33d..051b92bbabce5dfdd7edb17455d0f7b036475c2d 100644 (file)
@@ -2532,6 +2532,12 @@ This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 8 and
    translation table entries for a given stage of translation for a particular
    translation regime.
 
+Armv8.3-A
+~~~~~~~~~
+
+-  Pointer Authentication features of Armv8.3-A are unconditionally enabled so
+   that lower ELs are allowed to use them without causing a trap to EL3.
+
 Armv7-A
 ~~~~~~~
 
index 03b977e369e30f81c3d40e9cf4ebadf1e0823468..143c70c3912289e39f204a99d7a86a00e7527180 100644 (file)
         *
         * SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts
         *  to EL3 when executing at any EL.
+        *
+        * SCR_EL3.{API,APK}: For Armv8.3 pointer authentication feature,
+        * disable traps to EL3 when accessing key registers or using pointer
+        * authentication instructions from lower ELs.
         * ---------------------------------------------------------------------
         */
-       mov     x0, #((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \
+       mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT | \
+                               SCR_API_BIT | SCR_APK_BIT) \
                        & ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT))
        msr     scr_el3, x0
 
index a6022cb01eede898b2b2a4d936ae2aca89494055..e6842e148d45136f3ecdb9a3a33f904a2c138b24 100644 (file)
 /* SCR definitions */
 #define SCR_RES1_BITS          ((U(1) << 4) | (U(1) << 5))
 #define SCR_FIEN_BIT           (U(1) << 21)
+#define SCR_API_BIT            (U(1) << 17)
+#define SCR_APK_BIT            (U(1) << 16)
 #define SCR_TWE_BIT            (U(1) << 13)
 #define SCR_TWI_BIT            (U(1) << 12)
 #define SCR_ST_BIT             (U(1) << 11)
 #define VTTBR_BADDR_SHIFT      U(0)
 
 /* HCR definitions */
+#define HCR_API_BIT            (ULL(1) << 41)
+#define HCR_APK_BIT            (ULL(1) << 40)
 #define HCR_RW_SHIFT           U(31)
 #define HCR_RW_BIT             (ULL(1) << HCR_RW_SHIFT)
 #define HCR_AMO_BIT            (ULL(1) << 5)
index acc8d6d26c61b14954c7041095fa835389785a76..d3984a2890afebcd2fad952e278d1adb89adb972 100644 (file)
@@ -290,6 +290,7 @@ void cm_prepare_el3_exit(uint32_t security_state)
        uint32_t sctlr_elx, scr_el3, mdcr_el2;
        cpu_context_t *ctx = cm_get_context(security_state);
        int el2_unused = 0;
+       uint64_t hcr_el2 = 0;
 
        assert(ctx);
 
@@ -309,13 +310,20 @@ void cm_prepare_el3_exit(uint32_t security_state)
                         * EL2 present but unused, need to disable safely.
                         * SCTLR_EL2 can be ignored in this case.
                         *
-                        * Initialise all fields in HCR_EL2, except HCR_EL2.RW,
-                        * to zero so that Non-secure operations do not trap to
-                        * EL2.
-                        *
-                        * HCR_EL2.RW: Set this field to match SCR_EL3.RW
+                        * Set EL2 register width appropriately: Set HCR_EL2
+                        * field to match SCR_EL3.RW.
                         */
-                       write_hcr_el2((scr_el3 & SCR_RW_BIT) ? HCR_RW_BIT : 0);
+                       if (scr_el3 & SCR_RW_BIT)
+                               hcr_el2 |= HCR_RW_BIT;
+
+                       /*
+                        * For Armv8.3 pointer authentication feature, disable
+                        * traps to EL2 when accessing key registers or using
+                        * pointer authentication instructions from lower ELs.
+                        */
+                       hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT);
+
+                       write_hcr_el2(hcr_el2);
 
                        /*
                         * Initialise CPTR_EL2 setting all fields rather than